﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Instruments;
using I2CDll;

namespace Cali
{
    public struct DualTestFlag
    {
        public bool _bPSU1TestEn;
        public bool _bPSU2TestEn;
        public bool _bItem1TestEn;
    }
    public class Calibration
    {
        public string _sTest_name;
        public string[] _sLoadAddr;
        public string[] _sLoadChan;
        public string[] _sLoadType;
        public string[] _fVinSet;       //Source设定值
        public string[] _fFCinSet;      //Source设定值
        public float[] _Vmax;
        public float[] _Vmin;
        public string[,] _sCurrs;

        public double[,] _fViMes;
        public double[,] _fIiMes;
        public double[,] _fPiMes;
        public double[,,] _fVoMes;
        public double[,,] _fIoMes;

        public IniConfig Ininfo;
        public int IndexCurrentItem;
        public bool bStopFlag;
        public DualTestFlag DualTest;

        public static Source[] Sources;
        public static ELoad[] ELoads;
        public static PowerMeter[] PowerMeters;
        public byte[] upAddress;
        public byte[] eepAddress;
        public I2C i2C;

        public Calibration()
        {
            Ininfo = Form_Main.m_Ininfo;
            IndexCurrentItem = 0;

            _sCurrs = new string[5, 10];

            _fVinSet = new string[5];
            _fFCinSet = new string[5];
            
            _fViMes = new double[2,5];  //2个PSU
            _fIiMes = new double[2,5];
            _fPiMes = new double[2,5];
            _fIoMes = new double[2,Ininfo._nLoad_No, 5];
            _fVoMes = new double[2,Ininfo._nLoad_No, 5];

            Sources = new Source[2];
            ELoads = new ELoad[4];
            PowerMeters = new PowerMeter[2];

            upAddress = new byte[2];
            eepAddress = new byte[2];

            byte.TryParse(Ininfo._sAddressPSU, out upAddress[0]);
            byte.TryParse(Ininfo._sAddressPSU2, out upAddress[1]);
            byte.TryParse(Ininfo._sAddressEEP, out eepAddress[0]);
            byte.TryParse(Ininfo._sAddressEEP2, out eepAddress[1]);

            try
            {
                i2C = new I2C(Ininfo._sTypeI2CIO);
            }
            catch (Exception ex)
            {
                throw (new ApplicationException(ex.Message));
            }

            //_sLoadAddr = new string[10];
            //_sLoadChan = new string[10];
            //_sLoadType = new string[10];
        }

        /// <summary>
        /// 设备对象初始化
        /// </summary>
        /// <returns>初始化错误信息</returns>
        public string InstrumentsInit()
        {
            Visa visa;
            string sRet = string.Empty;
            int Count = Ininfo._bDual ? 4 : 2;

            Form_Ins.lsLoadType = new List<string>();
            try
            {
                for (int i = 0; i < Count; i++)
                {
                    visa = new Visa(Ininfo._sELoads[i]);

                    if (visa._szDesc.Contains(ELoad_Chroma6314._sType))
                    {
                        ELoads[i] = new ELoad_Chroma6314(Ininfo._sELoads[i]);
                        Form_Ins.lsLoadType.Add("6314");
                    }
                    else if (visa._szDesc.Contains(ELoad_Chroma63203._sType))
                    {
                        ELoads[i] = new ELoad_Chroma63203(Ininfo._sELoads[i]);
                        Form_Ins.lsLoadType.Add("63203");
                    }
                    else if (visa._szDesc.Contains(ELoad_Chroma63205._sType))
                    {
                        ELoads[i] = new ELoad_Chroma63205(Ininfo._sELoads[i]);
                        Form_Ins.lsLoadType.Add("63205");
                    }
                    else if (visa._szDesc.Contains(ELoad_IT87._sType))
                    {
                        ELoads[i] = new ELoad_IT87(Ininfo._sELoads[i]);
                        Form_Ins.lsLoadType.Add("IT87");
                    }
                    else
                    {
                        Form_Ins.lsLoadType.Add("");
                        sRet += "电子负载" + (i + 1).ToString() + ": " + Ininfo._sELoads[i] + "通讯失败！\r\n";
                    }

                    if (ELoads[i] != null)
                        ELoads[i].Init();
                }

                for (int i = 0; i < Count / 2; i++)
                {
                    visa = new Visa(Ininfo._sSources[i]);

                    if (visa._szDesc.Contains(ACS_Chroma6530._sType))
                        Sources[i] = new ACS_Chroma6530(Ininfo._sSources[i]);
                    else if (visa._szDesc.Contains(DCS_Chroma62024P._sType))
                        Sources[i] = new DCS_Chroma62024P(Ininfo._sSources[i]);
                    else if (visa._szDesc.Contains(DCS_Chroma62100H._sType))
                        Sources[i] = new DCS_Chroma62100H(Ininfo._sSources[i]);
                    else
                        sRet += "Source" + (i + 1).ToString() + ": " + Ininfo._sSources[i] + "通讯失败！\r\n";
                    if (Sources[i] != null)
                        Sources[i].Init();

                    visa = new Visa(Ininfo._sPowerMeters[i]);

                    if (visa._szDesc.Contains(PM_Chroma66202._sType))
                    {
                        PowerMeters[i] = new PM_Chroma66202(Ininfo._sPowerMeters[i]);
                    }
                    else if (visa._szDesc.Contains(PM_Chroma66205._sType))
                    {
                        PowerMeters[i] = new PM_Chroma66205(Ininfo._sPowerMeters[i]);
                    }
                    else if (visa._szDesc.Contains(PM_ZLG310._sType))
                    {
                        PowerMeters[i] = new PM_ZLG310(Ininfo._sPowerMeters[i]);
                    }
                    else
                        sRet += "功率计" + (i + 1).ToString() + ": " + Ininfo._sPowerMeters[i] + "通讯失败！\r\n";
                    if (PowerMeters[i] != null)
                        PowerMeters[i].Init();
                }
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
            return sRet;
        }

        /// <summary>
        /// 校准流程
        /// </summary>
        public void Run_Ini_Test()
        {
            while(IndexCurrentItem < Ininfo._sItemsTest.Length && Ininfo._sItemsTest[IndexCurrentItem].Equals(string.Empty))
            {
                if (bStopFlag)
                    break;
                switch (Ininfo._sItemsTest[IndexCurrentItem])
                {
                    case "VR":
                        {
                            Ininfo.ReadVRConfig();

                        }
                        break;
                    case "CAL":
                        {
                            Ininfo.ReadCALConfig();
                            Cali_CaliSub();
                        }
                        break;
                    case "DVR":
                        {

                        }
                        break;
                    default:
                        {
                            if(int.TryParse(Ininfo._sItemsTest[IndexCurrentItem], out int numberItem))
                            {
                                Ininfo.ReadNumberConfig(Ininfo._sItemsTest[IndexCurrentItem]);
                            }
                        }
                        break;
                }
                IndexCurrentItem++;
            }
        }

        /// <summary>
        /// 主函数：数据收集及计算
        /// </summary>
        /// <returns></returns>
        public bool Cali_CaliSub()
        {
            string sLog;
            string sTimeLog;
            int nStep;

            sLog = IndexCurrentItem.ToString() + ". " + Ininfo._sTestNames[IndexCurrentItem];
            //  dgvTestItems "Testing"
            for (int LineIndex = 0; LineIndex < 2; LineIndex++)
            {
                for (int row = 0; row < 5; row++)
                {
                    nStep = LineIndex * 5 + row;
                    //设定负载
                    Cali_SetLoad(row);
                    if (row.Equals(0))
                    {
                        if(Sources[0] != null)
                            Sources[0].Set_VFC(_fVinSet[LineIndex], _fFCinSet[LineIndex]);

                        if (Ininfo._bDual && Sources[1] != null)
                            Sources[1].Set_VFC(_fVinSet[LineIndex], _fFCinSet[LineIndex]);
                    }

                    Cali_GetOutputMes(row);
                    Cali_GetInputMes(row);
                }
            }

            return true;
        }


        /// <summary>
        /// 设定负载
        /// </summary>
        /// <param name="Index">组序号</param>

        public void Cali_SetLoad(int Index)     //5
        {
            string[] sCurr;

            switch(Index)
            {
                case 0:
                    sCurr = Ininfo._sCurr1;
                    break;
                case 1:
                    sCurr = Ininfo._sCurr2;
                    break;
                case 2:
                    sCurr = Ininfo._sCurr3;
                    break;
                case 3:
                    sCurr = Ininfo._sCurr4;
                    break;
                case 4:
                    sCurr = Ininfo._sCurr5;
                    break;
                default:
                    sCurr = new string[] { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" };
                    break;
            }

            for (int chan = 0; chan < Ininfo._nLoad_No; chan++) //3
            {
                SetChannelCurr(Ininfo._sLoad_Indexs[chan], Ininfo._sLoad_Chan[chan], sCurr[chan]);
                if (Ininfo._bDual)
                    SetChannelCurr(Ininfo._sLoad_Indexs2[chan], Ininfo._sLoad_Chan2[chan], sCurr[chan]);
            }
        }

        /// <summary>
        /// 设定通道电流
        /// </summary>
        /// <param name="ELoadIndex">负载相对地址</param>
        /// <param name="chan">通道地址</param>
        /// <param name="curr">电流值</param>
        public void SetChannelCurr(string ELoadIndex, string chan, string curr)
        {
            int index = int.Parse(ELoadIndex);
            if (ELoads[index] == null)
                return;
            ELoads[index].SetChannelCurr(chan, curr);
        }

        public void Cali_EnterCalibrantion()
        {
            bool Flag1 = true,
                Flag2 = true;

            if(DualTest._bPSU1TestEn)
            {
                if (IntoCaliMode(upAddress[0]))
                    Form_Main.PSU1Log.Text += "PSU 1 第一次发送进入校准指令成功！\n";
                else
                {
                    Form_Main.PSU1Log.Text += "PSU 1 第一次发送进入校准指令失败！\n";
                    Flag1 = false;
                }
            }

            if(DualTest._bPSU2TestEn)
            {
                if(IntoCaliMode(upAddress[1]))
                    Form_Main.PSU2Log.Text += "PSU 2 第一次发送进入校准指令成功！\n";
                else
                {
                    Form_Main.PSU2Log.Text += "PSU 2 第一次发送进入校准指令失败！\n";
                    Flag2 = false;
                }
            }

            if (Flag1.Equals(false) && Flag2.Equals(false))
                Thread.Sleep(2000);
        }

        public bool IntoCaliMode(byte add)
        {
            byte[] w_data = new byte[20];
            byte[] r_data = new byte[20];

            w_data[0] = 0x2D;
            w_data[1] = 0x04;
            w_data[2] = 0x11;
            w_data[3] = 0x13;
            w_data[4] = 0x17;
            w_data[5] = 0x19;

            i2C.PMBus_Block_Write(add, 6, w_data);

            w_data[0] = 0x2C;
            w_data[1] = 0x21;
            i2C.PMBus_Block_Write(add, 2, w_data);
            Thread.Sleep(10);

            i2C.PMBus_Block_Read(add, 0x2C, 1, r_data);

            return r_data[0].Equals(0x21);
        }

        /// <summary>
        /// 获取输出电压，电流值
        /// </summary>
        /// <param name="Index">组序号</param>
        public void Cali_GetOutputMes(int Index)        //5
        {
            for (int chan = 0; chan < Ininfo._nLoad_No; chan++)  //3
            {
                GetChannelVC(Ininfo._sLoad_Indexs[chan], Ininfo._sLoad_Chan[chan], out _fVoMes[0, chan, Index], out _fIoMes[0, chan, Index]);
                if (Ininfo._bDual)
                    GetChannelVC(Ininfo._sLoad_Indexs2[chan], Ininfo._sLoad_Chan2[chan], out _fVoMes[1, chan, Index], out _fIoMes[1, chan, Index]);
            }
        }

        /// <summary>
        /// 获取通道电压，电流值
        /// </summary>
        /// <param name="ELoadIndex">负载相对地址</param>
        /// <param name="chan">通道地址</param>
        /// <param name="volt">电压值</param>
        /// <param name="curr">电流值</param>
        public void GetChannelVC(string ELoadIndex, string chan, out double volt, out double curr)
        {
            curr = 0;
            volt = 0;
            int index = int.Parse(ELoadIndex);
            if (ELoads[index] == null)
                return;

            volt = ELoads[index].MeasChannelVolt(chan);
            curr = ELoads[index].MeasChannelCurr(chan);
        }

        /// <summary>
        /// 获取输入电压，电流，功率值
        /// </summary>
        /// <param name="Index">组序号</param>
        public void Cali_GetInputMes(int Index) //5
        {
            int count = Ininfo._bDual ? 2 : 1;
            for (int i = 0; i < count; i++)
            {
                if (PowerMeters[0] == null)
                {
                    _fViMes[i, Index] = Sources[i].Meas_Volt();
                    _fIiMes[i, Index] = Sources[i].Meas_Curr();
                    _fPiMes[i, Index] = Sources[i].Meas_Power();
                }
                else
                {
                    _fViMes[i, Index] = PowerMeters[i].Meas_Volt();
                    _fIiMes[i, Index] = PowerMeters[i].Meas_Curr();
                    _fPiMes[i, Index] = PowerMeters[i].Meas_Power();
                }
            }
        }
    }
}
